package com.zlkj.pro.modular.app.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.system.api.pojo.user.SysUserDTO;
import cn.stylefeng.roses.kernel.system.api.pojo.user.request.SysUserRequest;
import cn.stylefeng.roses.kernel.system.modular.user.service.SysUserService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zlkj.pro.core.consts.ProjectConstants;
import com.zlkj.pro.core.exception.BusinessException;
import com.zlkj.pro.core.util.ConvertUtil;
import com.zlkj.pro.modular.admin.entity.Config;
import com.zlkj.pro.modular.admin.model.dto.DashboardDTO;
import com.zlkj.pro.modular.admin.model.vo.UserVO;
import com.zlkj.pro.modular.admin.service.ConfigService;
import com.zlkj.pro.modular.app.entity.GdRes;
import com.zlkj.pro.modular.app.mapper.AppCustomerMapper;
import com.zlkj.pro.modular.app.mapper.AppUserMapper;
import com.zlkj.pro.modular.app.service.AppCustomerContactsService;
import com.zlkj.pro.modular.app.service.AppCustomerService;
import com.zlkj.pro.modular.business.entity.CustomerContactsEntity;
import com.zlkj.pro.modular.business.entity.CustomerEntity;
import com.zlkj.pro.modular.business.entity.ReportEntity;
import com.zlkj.pro.modular.business.mapper.ReportMapper;
import com.zlkj.pro.modular.business.mapper.TCustomerMapper;
import com.zlkj.pro.modular.business.model.dto.CustomerContactsDTO;
import com.zlkj.pro.modular.business.model.dto.CustomerDTO;
import com.zlkj.pro.modular.business.model.vo.AgentVO;
import com.zlkj.pro.modular.business.model.vo.CustomerVO;
import com.zlkj.pro.modular.business.service.CustomerContactsService;
import com.zlkj.pro.modular.business.service.ReportService;
import com.zlkj.pro.modular.business.service.TCustomerService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.zlkj.pro.core.exception.enums.BusinessExceptionEnum.BUSINESS_EXCEPTION;

/**
 * @author liyang
 * @date 2024/4/6
 * @time 14:34
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class AppCustomerServiceImpl extends ServiceImpl<TCustomerMapper, CustomerEntity> implements AppCustomerService {

    @Autowired
    private AppCustomerMapper appCustomerMapper;

    @Autowired
    private AppUserMapper appUserMapper;

    @Autowired
    private ConfigService configService;

    @Autowired
    private ReportService reportService;

    @Autowired
    private CustomerContactsService customerContactsService;

    @Autowired
    private AppCustomerContactsService appCustomerContactsService;



    @Override
    public List<CustomerVO> findList(CustomerDTO dto) {
        if (dto.getUserId() == null) throw new BusinessException(BUSINESS_EXCEPTION, "userId不能为空");

        // 查询个人代理商信息
        AgentVO vo = appUserMapper.getAgentInfo(dto.getUserId());
        dto.setAgentId(vo.getId());

        // 角色赋值
        extracted(dto);
        if (dto.getRoleId() != 4) {
            dto.setQueryType(1);// 非经理按权限查询
        }

        List<CustomerVO> list = appCustomerMapper.findList(dto);
        // 分页处理
        if (dto.getPageNum() != null && dto.getPageSize() != null) {
            list = list.stream().skip((dto.getPageNum() - 1) * dto.getPageSize()).limit(dto.getPageSize()).collect(Collectors.toList());
        }
        // 截取前20条记录
        /*if (CollectionUtils.isNotEmpty(list) && list.size() > 20) {
            list = list.stream().limit(20).collect(Collectors.toList());
        }*/
        return list;
    }

    @Autowired
    private SysUserService sysUserService;

    private void extracted(CustomerDTO dto) {
        SysUserRequest sysUserRequest = new SysUserRequest();
        sysUserRequest.setUserId(dto.getUserId());
        SysUserDTO currentUser = sysUserService.detail(sysUserRequest);
        Long roleId = currentUser.getGrantRoleIdList().get(0);
        if (ProjectConstants.ROLE_ID_BMSH_MANAGER.equals(roleId)) {
            dto.setRoleId(1);
        } else if (ProjectConstants.ROLE_ID_BMSH_YG.equals(roleId)) {
            dto.setRoleId(2);
        } else if (ProjectConstants.ROLE_ID_AGENT_MANAGER.equals(roleId)) {
            dto.setRoleId(3);
        } else if (ProjectConstants.ROLE_ID_JL.equals(roleId)) {
            dto.setRoleId(4);
        } else if (ProjectConstants.ROLE_ID_YG.equals(roleId)) {
            dto.setRoleId(5);
        }
    }

    @Override
    public List<UserVO> findSubordinateList(Long userId, String query) {
        if (userId == null) throw new BusinessException(BUSINESS_EXCEPTION, "userId不能为空");

        List<UserVO> list = appCustomerMapper.findSubordinateList(userId, query);
        return list;
    }

    @Override
    public boolean delete(CustomerDTO dto) {
        // 判断是否有关联报备单
        if (reportService.count(new LambdaQueryWrapper<ReportEntity>()
                .eq(ReportEntity::getCustomerId, dto.getId())) > 0) {
            throw new BusinessException(BUSINESS_EXCEPTION, "当前客户已存在报备记录，不可删除");
        }
        return super.removeById(dto);
    }


    @Autowired
    private ReportMapper reportMapper;

    @Override
    public CustomerVO findDetail(CustomerDTO dto) {
        CustomerVO customer = appCustomerMapper.findDetail(dto);
        extracted(dto);
        if (dto.getRoleId() == 4) {
            // 添加是否是自己或者自己下属创建但报备单标识
            List<Long> userIds = reportMapper.queryOurUserIds(dto.getUserId());
            customer.setOurReport(userIds.contains(customer.getCreateUser()));
        } else {
            customer.setOurReport(true);
        }
        return customer;
    }


    @Override
    public boolean add(CustomerDTO dto) {
        // 客户名称必须输入
        if (StringUtils.isBlank(dto.getName())) {
            throw new BusinessException(BUSINESS_EXCEPTION, "客户名称必须输入");
        }

        // 信用代码，保存时统一转换为大写字符
        if (StringUtils.isNotBlank(dto.getUscc())) {
            dto.setUscc(dto.getUscc().toUpperCase());
        }
        // 客户名称、信用代码、详细地址，手机号 前后去空格
        if (StringUtils.isNotBlank(dto.getName())) dto.setName(dto.getName().trim());
        if (StringUtils.isNotBlank(dto.getUscc())) dto.setUscc(dto.getUscc().trim());
        if (StringUtils.isNotBlank(dto.getAddressDetail())) dto.setAddressDetail(dto.getAddressDetail().trim());
        if (StringUtils.isNotBlank(dto.getPhone())) dto.setPhone(dto.getPhone().trim());

        AgentVO vo = appUserMapper.getAgentInfo(dto.getUserId());
        dto.setAgentId(vo.getId());
        dto.setCreateUser(dto.getCreateUserId());// 客户负责人
        dto.setUpdateTime(new Date());
        CustomerEntity entity = ConvertUtil.turn(dto, CustomerEntity.class);
        // 检查唯一性
        // check(entity);
        if (dto.getType() == 2) {
            //小程序新增个人客户，信用代码即使输入了也不用保存
            dto.setUscc(null);
        }
        return super.save(entity);
    }

    @Override
    public boolean edit(CustomerDTO dto) {
        dto.setCreateUser(dto.getCreateUserId());// 客户负责人
        dto.setUpdateUser(dto.getUserId());// 当前登录人作为更新

        // 信用代码，保存时统一转换为大写字符
        if (StringUtils.isNotBlank(dto.getUscc())) {
            dto.setUscc(dto.getUscc().toUpperCase());
        }
        // 客户名称、信用代码、详细地址，手机号 前后去空格
        if (StringUtils.isNotBlank(dto.getName())) dto.setName(dto.getName().trim());
        if (StringUtils.isNotBlank(dto.getUscc())) dto.setUscc(dto.getUscc().trim());
        if (StringUtils.isNotBlank(dto.getAddressDetail())) dto.setAddressDetail(dto.getAddressDetail().trim());
        if (StringUtils.isNotBlank(dto.getPhone())) dto.setPhone(dto.getPhone().trim());

        CustomerEntity entity = ConvertUtil.turn(dto, CustomerEntity.class);
        // 检查唯一性
        // check(entity);
        if (dto.getCustomerStatus() == 3) {
            // 失效客户的时候相关联系人也失效
            customerContactsService.update(new LambdaUpdateWrapper<CustomerContactsEntity>()
                    .set(CustomerContactsEntity::getContactStatus, 2)
                    .eq(CustomerContactsEntity::getCustomerId, dto.getId()));
        }
        return super.updateById(entity);
    }


    @Override
    public boolean addPro(CustomerDTO dto) {
        // 客户名称必须输入
        if (StringUtils.isBlank(dto.getName())) {
            throw new BusinessException(BUSINESS_EXCEPTION, "客户名称必须输入");
        }

        for (CustomerContactsDTO cc : dto.getContacts()){
            cc.setUserId(dto.getUserId());
        }

        // 最少需要一个联系人信息
        if (CollectionUtils.isEmpty(dto.getContacts())) {
            throw new BusinessException(BUSINESS_EXCEPTION, "最少需要一个联系人信息");
        }

        // 信用代码，保存时统一转换为大写字符
        if (StringUtils.isNotBlank(dto.getUscc())) {
            dto.setUscc(dto.getUscc().toUpperCase());
        }
        // 客户名称、信用代码、详细地址，手机号 前后去空格
        if (StringUtils.isNotBlank(dto.getName())) dto.setName(dto.getName().trim());
        if (StringUtils.isNotBlank(dto.getUscc())) dto.setUscc(dto.getUscc().trim());
        if (StringUtils.isNotBlank(dto.getAddressDetail())) dto.setAddressDetail(dto.getAddressDetail().trim());
        if (StringUtils.isNotBlank(dto.getPhone())) dto.setPhone(dto.getPhone().trim());

        AgentVO vo = appUserMapper.getAgentInfo(dto.getUserId());
        dto.setAgentId(vo.getId());
        dto.setCreateUser(dto.getCreateUserId());// 客户负责人
        dto.setUpdateTime(new Date());
        CustomerEntity entity = ConvertUtil.turn(dto, CustomerEntity.class);
        // 检查唯一性
        // check(entity);
        if (entity.getType() == 2) {
            //小程序新增个人客户，信用代码即使输入了也不用保存
            entity.setUscc(null);
        }
        // 重新组装客户地址用省市区code
        fixAddress(entity);
        super.save(entity);

        // 添加联系人
        for (CustomerContactsDTO contact : dto.getContacts()) {
            contact.setCustomerId(entity.getId().intValue());
            appCustomerContactsService.add(contact);
        }
        return true;
    }

    @Override
    public boolean editPro(CustomerDTO dto) {
        dto.setCreateUser(dto.getCreateUserId());// 客户负责人
        dto.setUpdateUser(dto.getUserId());// 当前登录人作为更新

        // 最少需要一个联系人信息
        if (CollectionUtils.isEmpty(dto.getContacts())) {
            throw new BusinessException(BUSINESS_EXCEPTION, "最少需要一个联系人信息");
        }

        for (CustomerContactsDTO cc : dto.getContacts()){
            cc.setUserId(dto.getUserId());
        }

        // 信用代码，保存时统一转换为大写字符
        if (StringUtils.isNotBlank(dto.getUscc())) {
            dto.setUscc(dto.getUscc().toUpperCase());
        }
        // 客户名称、信用代码、详细地址，手机号 前后去空格
        if (StringUtils.isNotBlank(dto.getName())) dto.setName(dto.getName().trim());
        if (StringUtils.isNotBlank(dto.getUscc())) dto.setUscc(dto.getUscc().trim());
        if (StringUtils.isNotBlank(dto.getAddressDetail())) dto.setAddressDetail(dto.getAddressDetail().trim());
        if (StringUtils.isNotBlank(dto.getPhone())) dto.setPhone(dto.getPhone().trim());

        CustomerEntity entity = ConvertUtil.turn(dto, CustomerEntity.class);
        // 检查唯一性
        // check(entity);
        if (dto.getCustomerStatus() == 3) {
            // 失效客户的时候相关联系人也失效
            customerContactsService.update(new LambdaUpdateWrapper<CustomerContactsEntity>()
                    .set(CustomerContactsEntity::getContactStatus, 2)
                    .eq(CustomerContactsEntity::getCustomerId, dto.getId()));
        }

        // 重新组装客户地址用省市区code
        fixAddress(entity);
        super.updateById(entity);

        // 删除不在本次更新id范围内的所有联系人
        customerContactsService.remove(new LambdaQueryWrapper<CustomerContactsEntity>()
                .eq(CustomerContactsEntity::getCustomerId, dto.getId())
                .notIn(CustomerContactsEntity::getId, dto.getContacts().stream().map(CustomerContactsDTO::getId).collect(Collectors.toList())));

        for (CustomerContactsDTO contact : dto.getContacts()){
            contact.setCustomerId(entity.getId().intValue());
            if(contact.getId() == null){
                // 新增联系人
                appCustomerContactsService.add(contact);
            }else{
                // 更新联系人
                appCustomerContactsService.edit(contact);
            }
        }
        return true;
    }

    private void fixAddress(CustomerEntity entity) {
        String address = appCustomerMapper.findAddress(
                entity.getAddressProvince(),
                entity.getAddressCity(),
                entity.getAddressArea());
        entity.setAddress(address);
    }

    private void check(CustomerEntity dto) {
        Long id = 0L;
        if (dto.getId() != null) {
            id = dto.getId();
        }
        //企业类型：校验 名称+信用代码唯一
        if (dto.getType() == 1 && super.count(new LambdaQueryWrapper<CustomerEntity>()
                .ne(CustomerEntity::getId, id)
                .eq(CustomerEntity::getName, dto.getName())
                .eq(CustomerEntity::getUscc, dto.getUscc())
                .eq(CustomerEntity::getDelFlag, YesOrNotEnum.N.getCode())) > 0) {
            throw new BusinessException(BUSINESS_EXCEPTION, "当前客户已存在");
        }

        //个人类型：校验 姓名+手机号唯一，不能重复添加
        if (dto.getType() == 2 && super.count(new LambdaQueryWrapper<CustomerEntity>()
                .ne(CustomerEntity::getId, id)
                .eq(CustomerEntity::getName, dto.getName())
                .eq(CustomerEntity::getPhone, dto.getPhone())
                .eq(CustomerEntity::getDelFlag, YesOrNotEnum.N.getCode())) > 0) {
            throw new BusinessException(BUSINESS_EXCEPTION, "当前客户已存在");
        }
    }

    @Override
    public List<String> findClassifyList() {
        LambdaQueryWrapper<Config> queryWrapper = new LambdaQueryWrapper<Config>();
        queryWrapper
                .eq(Config::getCode, "CUSTOMER_TYPES")
                .eq(Config::getDelFlag, YesOrNotEnum.N.getCode());
        return Arrays.asList(configService.getOne(queryWrapper).getValue().split(","));
    }

    @Override
    public List<Map<String, String>> findArea(String parentId) {

        List<Map<String, String>> map = appCustomerMapper.findArea(parentId);
        if (CollectionUtils.isEmpty(map)) return map;
        map.forEach(m -> {
            int levelType = Integer.parseInt(m.get("levelType"));
            String parentPath = m.get("parentPath");
            String[] parentPaths = parentPath.split(",");
            m.put("code",parentPaths[levelType-1]);

            m.remove("parentPath");
            m.remove("province");
            m.remove("city");
            m.remove("district");
        });
        return map;
    }

    private final TCustomerService customerService;
    private String urlBase = "https://restapi.amap.com/v3/geocode/geo";
    String key = "49f06e8b625056871e47a18800b667a4";


    @SneakyThrows
    @Override
    public void fixAddress(String type) {
        if (type.equals("1")) {
            // type = 1 补全省市区

            // 查询要刷新的客户数据
//            List<Long> customerIds = appCustomerMapper.findNeedFixAddress();
            List<CustomerEntity> customers = appCustomerMapper.findCustomerList();
            // customers 取前1000条
//            customers = customers.stream().limit(1000).collect(Collectors.toList());
            List<Map<String, String>> areas = appCustomerMapper.findAreaPath();

            for (CustomerEntity customer : customers) {
                if (StringUtils.isNotBlank(customer.getAddress())) {
                    String adcode = getAdcode(customer.getAddress());
                    Optional<Map<String, String>> o = areas.stream().filter(a -> a.get("id").equals(adcode)).findFirst();
                    if (o.isPresent()) {
                        String parentPath = o.get().get("parentPath");
                        String[] parentPaths = parentPath.split(",");
                        customer.setAddressProvince(parentPaths[0]);
                        customer.setAddressCity(parentPaths[1]);
                        if (parentPaths.length > 2) {
                            customer.setAddressArea(parentPaths[2]);
                        }
                        //System.out.println("客户数据：" + customer.getId() + ":" + customer.getAddressProvince() + ":" + customer.getAddressCity() + ":" + customer.getAddressArea());
                    }
                }
            }
            customerService.updateBatchById(customers);
        } else if (type.equals("2")) {
            // type = 2 移除省市区名称 其他批量截取到备注

            //查询所有需要刷新的客户数据
            List<CustomerEntity> customers = appCustomerMapper.findCustomerList();

            //查询所有省市区名
            List<Map<String,String>> areaList = appCustomerMapper.findAreaName();

            //将查询结果按省分组 key:省code，value:省下所有省市区名
            Map<String, List<String>> provinceMap = areaList.stream().collect(Collectors.groupingBy(area -> area.get("provinceCode"),
                    Collectors.mapping(area -> area.get("name"), Collectors.toList())));

            //遍历客户数据
            for (CustomerEntity customer : customers) {

                //获取当前客户所在省的地区数据
                List<String> provinceAreaList = provinceMap.get(customer.getAddressProvince());
                if (null == provinceAreaList || provinceAreaList.isEmpty()) continue;

                String newAddress = customer.getAddress();

                //遍历地区数据
                for (String area : provinceAreaList) {
                    if (StrUtil.startWith(newAddress, area)){
                        newAddress = StrUtil.subAfter(newAddress, area, Boolean.FALSE);
                    }
                }

                if (StrUtil.isBlank(customer.getAddressDetail())) {
                    customer.setAddressDetail(newAddress);
                } else {
                    customer.setRemark(StrUtil.isNotBlank(customer.getRemark()) ? (customer.getRemark() + "；" + newAddress) : newAddress);
                }

                System.out.println("customer：" + customer.getName() + ",address：" + customer.getAddress() + ",address-detail：" + customer.getAddressDetail() + ",remark：" + customer.getRemark());

            }
            customerService.updateBatchById(customers);
        } else if (type.equals("3")) {
            // type = 3 批量更新所在地址

            //查询所有需要刷新的客户数据
            List<CustomerEntity> customers = appCustomerMapper.findCustomerList();

            //查询所有省市区名
            List<Map<String,String>> areaList = appCustomerMapper.findAreaName();

            Map<String, String> areaMap = areaList.stream().collect(Collectors.toMap(area -> area.get("id"), area -> area.get("name"), (v1, v2) -> v1));

            for (CustomerEntity customer : customers) {

                //省
                String province = areaMap.getOrDefault(customer.getAddressProvince(), "");
                //市
                String city = areaMap.getOrDefault(customer.getAddressCity(), "");
                //区
                String area = areaMap.getOrDefault(customer.getAddressArea(), "");

                String oldAddress = customer.getAddress();

                customer.setAddress(province + city + area);

                System.out.println("customer：" + customer.getName() + ",old-address：" + oldAddress + ",new-address：" + customer.getAddress() + ",address-detail：" + customer.getAddressDetail() + ",remark：" + customer.getRemark());

            }
            customerService.updateBatchById(customers);
        }
    }

    private String getAdcode(String address) throws IOException {
        OkHttpClient client = new OkHttpClient();
        // URL和参数
        // 构造URL
        String encodedKey = URLEncoder.encode(key, String.valueOf(StandardCharsets.UTF_8));
        String encodedAddress = URLEncoder.encode(address, String.valueOf(StandardCharsets.UTF_8));
        String url = urlBase + "?key=" + encodedKey + "&address=" + encodedAddress;

        // 创建Request对象
        Request request = new Request.Builder()
                .url(url)
                .build();

        // 发送请求并获取响应
        Response response = client.newCall(request).execute();

        // 处理响应
        if (!response.isSuccessful()) {
            throw new IOException("Unexpected code " + response);
        }
        // GdRes res = response.body();
        GdRes res = JSON.parseObject(response.body().string(), GdRes.class);
        System.out.println("Response Body2 : " + JSON.toJSONString(res));

        List<Map<String, Object>> geos = res.getGeocodes();
        if (CollectionUtils.isNotEmpty(geos)) {
            String adcode = (String) geos.get(0).get("adcode");
            return adcode;
        }
        return null;
    }





}
